package com.legal.service.chat.impl;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.legal.domain.dto.ChatHistory;
import com.legal.service.chat.ChatHistoryService;
import lombok.RequiredArgsConstructor;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.*;

@RequiredArgsConstructor
@Primary
@Component
public class RedisChatHistory implements ChatHistoryService {
    private final StringRedisTemplate redisTemplate;
    private final ObjectMapper objectMapper;

    private static final String CHAT_HISTORY_HASH_KEY = "legal:history:hash:";
    private static final String CHAT_HISTORY_ZSET_KEY = "legal:history:zset:";
    private final static String PREFIX = "legal:message:";

    /**
     * 保存会话记录,通过hash存储完整结构，Zset存储chatId，用来维持顺序问题
     * 这个通常用来初始化（新建对话，更新历史记录的标题使用）
     * @param chatHistory 包含如下
     * userId 用户id
     * type 业务类型
     * chatId 会话id
     * title 会话标题
     */
    @Override
    public void save(ChatHistory chatHistory) {
        // 构建hash存储的大key，直接使用chatId
        String hashKey = CHAT_HISTORY_HASH_KEY+ chatHistory.getType() + ":" + chatHistory.getUserNo()+":"+ chatHistory.getChatId();
        //构建时间
        chatHistory.setUpdateTime(LocalDateTime.now());
        try {
            // 使用Hash结构存储各个字段
            redisTemplate.opsForHash().putAll(hashKey, Map.of(
                    "title", chatHistory.getTitle(),
                    "updateTime", chatHistory.getUpdateTime().toString() // 将时间转为字符串
            ));

            // 仍然使用ZSet维护更新时间排序
            updateChatTime(chatHistory);

        } catch (Exception e) {
            throw new RuntimeException("Failed to save chat history", e);
        }
    }

    /**
     * 更新聊天记录时间
     * @param chatHistory
     */
    @Override
    public void updateChatTime(ChatHistory chatHistory) {
        // 使用ZSet维护更新时间排序
        redisTemplate.opsForZSet().add(
                CHAT_HISTORY_ZSET_KEY + chatHistory.getType() + ":" + chatHistory.getUserNo(), // zset key的前缀
                chatHistory.getChatId(), // zset key（chatId作为key）
                System.currentTimeMillis() // zset value即score（更新时间）
        );
        // 更新hash里面的updateTime
        String hashKey = CHAT_HISTORY_HASH_KEY + chatHistory.getType() + ":" + chatHistory.getUserNo()+":"+ chatHistory.getChatId();
        redisTemplate.opsForHash().put(hashKey, "updateTime", LocalDateTime.now().toString());
    }

    @Override
    public List<ChatHistory> getChatHistories(String type, String userNo) {
        //获取 redis 中 userNo编号 对应的所有chatId
        List<String> chatIds = getChatIds(type, userNo);
        //遍历chatId，若为空则返回空列表
        if (chatIds.isEmpty()) {
            return Collections.emptyList();
        }
        //创建history对象
        List<ChatHistory> histories = new ArrayList<>();

        // 使用字符串类型的管道操作,返回的是所有的大key对应的结果
        List<Object> results = redisTemplate.executePipelined((RedisCallback<Object>) connection -> {
            for (String chatId : chatIds) {
                String hashKey = CHAT_HISTORY_HASH_KEY + type + ":" + userNo + ":" + chatId; //hashKey
                // 使用字符串操作而非字节数组
                connection.hGetAll(hashKey.getBytes(StandardCharsets.UTF_8));
            }
            return null;
        });

        // 处理结果
        for (int i = 0; i < results.size(); i++) {
            //获取Hash中的小key和value集合
            Map<String, String> entryMap = (Map<String, String>) results.get(i);
            //只要有值，就进行转换
            if (entryMap != null && !entryMap.isEmpty()) {
                ChatHistory history = new ChatHistory();
                //基础属性注入
                history.setUserNo(userNo);
                history.setType(type);
                history.setChatId(chatIds.get(i));
                history.setTitle(entryMap.get("title"));
                //时间属性注入
                String updateTimeStr = entryMap.get("updateTime");
                if (updateTimeStr != null) {
                    history.setUpdateTime(LocalDateTime.parse(updateTimeStr));
                }

                histories.add(history);
            }
        }
        return histories;
    }


    @Override
    public List<String> getChatIds(String type, String userNo) {
        // 从ZSet获取按时间排序的chatIds
        Set<String> chatIds = redisTemplate.opsForZSet().reverseRange( //reverseRange是按降序获取
                CHAT_HISTORY_ZSET_KEY + type + ":" + userNo, // ZSet的key
                0, -1 // 获取所有元素
        );

        // 遍历chatIds，获取每个chatId对应的chatHistory,如果chatId对应的chatHistory不存在，则创建一个空的chatHistory
        if (chatIds == null || chatIds.isEmpty()) {
            return Collections.emptyList();
        }
        return chatIds.stream().toList();//.sorted(String::compareTo)
    }

    @Override
    public void deleteChatHistory(String type, String userNo, String chatId) {
        // 从Hash中删除（使用完整key）
        redisTemplate.delete(CHAT_HISTORY_HASH_KEY + type + ":" + userNo+":" + chatId);

        // 从ZSet中删除
        redisTemplate.opsForZSet().remove(
                CHAT_HISTORY_ZSET_KEY + type + ":" + userNo,
                chatId
        );
        //绑定的对话历史删除
        redisTemplate.delete(PREFIX + chatId);
    }

    @Override
    public void editChatHistory(String type, String userNo, String chatId, String title) {
        //只需要修改hash中的title字段
        String hashKey = CHAT_HISTORY_HASH_KEY + type + ":" + userNo + ":" + chatId;
        redisTemplate.opsForHash().put(hashKey, "title", title);
    }
}